from cStringIO import StringIO

class Channel(object):
    def __init__(self, stream):
        self.stream = stream
    def close(self):
        self.stream.close()
    def send(self, data):
        raise NotImplementedError()
    def recv(self):
        raise NotImplementedError()


class NetstringChannel(Channel):
    MAX_FRAME_SIZE = 2 ** 32
    
    def send(self, data):
        raw = "%d:%s," % (len(data), data)
        self.stream.write(raw)
    def recv(self):
        length = 0
        while True:
            ch = self.stream.read(1)
            if ch == ":":
                break
            elif "0" <= ch <= "9":
                length = length * 10 + int(ch)
                if length > self.MAX_FRAME_SIZE:
                    raise ValueError("frame too long")
            else:
                raise ValueError("expected a digit")
        length = int(length)
        data = self.stream.read(length)
        ch = self.stream.read(1)
        if ch != ",":
            raise ValueError("expected ','")
        return data



n = NetstringChannel(StringIO("118:hello world,3:bye,"))
print n.recv()


